package com.javafactroy.kunlong.client.feign.dto;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.github.pagehelper.PageHelper;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import javax.persistence.Transient;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Data
@Accessors(chain = true)
public class PageInfoDto implements Serializable {


    private static final long serialVersionUID = 1L; //一会就说这个是做什么的

    @Transient
    @JsonInclude(JsonInclude.Include.NON_NULL)
    protected String dbType;

    @Transient
    @JsonInclude(JsonInclude.Include.NON_NULL)
    protected Integer pageSize;
    @Transient
    @JsonInclude(JsonInclude.Include.NON_NULL)
    protected Integer pageNum;

    @Transient
    @JsonInclude(JsonInclude.Include.NON_NULL)
    protected List<OrderByDto> orderBys;

    //@Transient
    @JsonInclude(JsonInclude.Include.NON_NULL)
    //@ExcelIgnore
    @ApiModelProperty("between")
    protected List<BetweenFields> between;

    @Transient
    //@ExcelIgnore
    @ApiModelProperty("NOT BETWEEN")
    @JsonInclude(JsonInclude.Include.NON_NULL)
    protected List<BetweenFields> notBetween;

    @Transient
    @JsonInclude(JsonInclude.Include.NON_NULL)
    Boolean tranField2Col;

    // field prop2col for example: dptId->dpt_id
    public void fields2Col() {
        if (ObjectUtil.isNotEmpty(tranField2Col) && !tranField2Col) {
            return;
        }
        if (between != null) {
            between.forEach(i -> i.field2Col());
        }
        if (notBetween != null) {
            notBetween.forEach(i -> i.field2Col());
        }
        if (ObjectUtil.isNotEmpty(orderBys)) {
            orderBys.forEach(i -> i.field2Col());
        }

    }

    /*
     * @params field
     * @params sort :  asc or desc
     * */
    public PageInfoDto orderBy(String field, String sort) {
        if (orderBys == null) {
            orderBys = new ArrayList<>();
        }
        orderBys.add(new OrderByDto().setSort(sort).setField(field));
        return this;
    }
    public PageInfoDto orderByDesc(String field) {
        return this.orderBy(field,"desc");
    }
    public PageInfoDto orderByAsc(String field) {
        return this.orderBy(field,"asc");
    }
    public void orderBy(String field) {
        orderBy(field, "asc");
    }


    public void startPage() {
        if (pageNum == null) {
            pageNum = 1;
        }
        if (pageSize == null) {
            pageSize = 2;
        }
        PageHelper.startPage(pageNum, pageSize);

    }

    public void startPageOrder() {
        this.fields2Col();
        startOrder();
        startPage();
    }
    public void startOrderBy() {
        this.fields2Col();
        startOrder();
    }
    public void startOrder() {
        if (ObjectUtil.isEmpty(orderBys)) {
            return;
        }
        List<String> orders = orderBys.stream().map(i -> i.getField() + " " + i.getSort()).collect(Collectors.toList());
        PageHelper.orderBy(StrUtil.join(",", orders));
    }

    List<BetweenFields> getBetween() {
        if (between == null) {
            between = new ArrayList<>();
        }
        return between;
    }

    List<BetweenFields> getNotBetween() {
        if (notBetween == null) {
            notBetween = new ArrayList<>();
        }
        return notBetween;
    }

    public PageInfoDto between(String field, Date date) {
        getBetween().add(new BetweenFields(field, date));
        return this;
    }

    public PageInfoDto betweenDate(String field, String start, String end) {
        Date sdate = DateUtil.parseDateTime(start);
        Date edate = DateUtil.parseDateTime(end);

        getBetween().add(new BetweenFields(field, sdate, edate));
        return this;
    }

    public PageInfoDto between(String field, Date start, Date end) {
        getBetween().add(new BetweenFields(field, start, end));
        return this;
    }

    public PageInfoDto between(String field, String start, String end) {
        getBetween().add(new BetweenFields(field, start, end));
        return this;
    }

    public PageInfoDto between(String field, Integer start, Integer end) {
        getBetween().add(new BetweenFields(field, start, end));
        return this;
    }

    public PageInfoDto between(String field, String start) {
        getBetween().add(new BetweenFields(field, start, start));
        return this;
    }

    public PageInfoDto like(String field, String value) {
        getBetween().add(new BetweenFields().like(field, value));
        return this;
    }

    public PageInfoDto in(String field, String value) {
        getBetween().add(new BetweenFields().in(field, value));
        return this;
    }

    //=
    public PageInfoDto eq(String field, Object value) {
        getBetween().add(new BetweenFields().eq(field, value));
        return this;
    }

    //<
    public PageInfoDto lt(String field, Object value) {
        getBetween().add(new BetweenFields().lt(field, value));
        return this;
    }

    //>
    public PageInfoDto gt(String field, Object value) {
        getBetween().add(new BetweenFields().gt(field, value));
        return this;
    }

    //<=
    public PageInfoDto le(String field, Object value) {
        getBetween().add(new BetweenFields().le(field, value));
        return this;
    }

    //>=
    public PageInfoDto ge(String field, Object value) {
        getBetween().add(new BetweenFields().ge(field, value));
        return this;
    }


    public PageInfoDto notBetween(String field, Date date) {
        getNotBetween().add(new BetweenFields(field, date));
        return this;
    }

    public PageInfoDto notBetween(String field, String s) {
        getNotBetween().add(new BetweenFields(field, s, s));
        return this;
    }

    public PageInfoDto notBetween(String field, String s, String e) {
        getNotBetween().add(new BetweenFields(field, s, e));
        return this;
    }

    public PageInfoDto notBetween(String field, Date start, Date end) {
        getNotBetween().add(new BetweenFields(field, start, end));
        return this;
    }

    public PageInfoDto notLike(String field, String value) {
        getNotBetween().add(new BetweenFields().like(field, value));
        return this;
    }

    public PageInfoDto notIn(String field, String value) {
        getNotBetween().add(new BetweenFields().in(field, value));
        return this;
    }

    public PageInfoDto notEq(String field, String value) {
        getNotBetween().add(new BetweenFields().eq(field, value));
        return this;
    }

    public Boolean checkInsertFlag(){
        return Boolean.FALSE;
    }
    /*
     *
     * between like in =
     *    > < >= <=
     * not between not like not in !=
     * */
    @Data
    @NoArgsConstructor
    public static class BetweenFields {

        String field;

        Object start;
        Object end;

        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
        Date startDate;
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
        Date endDate;

        String inValue;
        String likeValue;

        String eqType;//= > < >= <=
        Object eqValue;

        public BetweenFields(String field, Date start, Date end) {
            this.field = field;
            this.startDate = start;
            this.endDate = end;
        }

        public BetweenFields(String field, Object start, Object end) {
            this.field = field;
            this.start = start;
            this.end = end;
        }

        public BetweenFields(String field, Date start) {
            this(field, start, start);
        }

        public BetweenFields like(String field, String value) {
            this.field = field;
            this.likeValue = value;
            return this;
        }

        public BetweenFields in(String field, String value) {
            this.field = field;
            inValue = value;
            return this;

        }

        public BetweenFields eq(String field, Object value) {
            this.field = field;
            eqValue = value;
            eqType = "=";
            return this;
        }

        public BetweenFields lt(String field, Object value) {
            this.field = field;
            eqValue = value;
            eqType = "<";
            return this;
        }

        public BetweenFields gt(String field, Object value) {
            this.field = field;
            eqValue = value;
            eqType = ">";
            return this;
        }

        public BetweenFields le(String field, Object value) {
            this.field = field;
            eqValue = value;
            eqType = "<=";
            return this;
        }

        public BetweenFields ge(String field, Object value) {
            this.field = field;
            eqValue = value;
            eqType = ">=";
            return this;
        }

        public void field2Col() {
            field = StrUtil.toUnderlineCase(field);
        }


    }
}
